package com.punai.dataclean.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.punai.common.core.page.TableDataInfo;
import com.punai.common.utils.PageUtils;
import com.punai.config.domain.ConfigInventoryChapter;
import com.punai.config.domain.ConfigInventoryLib;
import com.punai.config.mapper.ConfigInventoryChapterMapper;
import com.punai.config.mapper.ConfigInventoryLibMapper;
import com.punai.dataclean.constants.IncomeDataConstanta;
import com.punai.dataclean.domain.IncomeDataClean;
import com.punai.dataclean.domain.IncomeDataCleanInfo;
import com.punai.dataclean.domain.vo.CostDataCleanVo;
import com.punai.dataclean.domain.vo.IncomeDataCleanVo;
import com.punai.dataclean.mapper.IncomeDataCleanInfoMapper;
import com.punai.dataclean.mapper.IncomeDataCleanMapper;
import com.punai.dataclean.service.IncomeDataCleanService;
import com.punai.externalccb.constants.CCBConstants;
import com.punai.externalccb.domain.EcoBqitem;
import com.punai.externalccb.domain.EcoBqitemmate;
import com.punai.externalccb.domain.EcoCbfeeitem;
import com.punai.externalccb.domain.EcoMeasureitem;
import com.punai.externalccb.mapper.EcoBqitemMapper;
import com.punai.externalccb.mapper.EcoBqitemmateMapper;
import com.punai.externalccb.mapper.EcoCbfeeitemMapper;
import com.punai.externalccb.mapper.EcoMeasureitemMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class IncomeDataCleanServiceImpl implements IncomeDataCleanService {
    @Autowired
    private ConfigInventoryChapterMapper configInventoryChapterMapper;
    @Autowired
    private ConfigInventoryLibMapper configInventoryLibMapper;
    @Autowired
    private EcoBqitemMapper ecoBqitemMapper;
    @Autowired
    private EcoCbfeeitemMapper cbfeeitemMapper;
    @Autowired
    private EcoBqitemmateMapper ecoBqitemmateMapper;

    @Autowired
    private EcoMeasureitemMapper ecoMeasureitemMapper;
    @Autowired
    private IncomeDataCleanMapper incomeDataCleanMapper;
    @Autowired
    private IncomeDataCleanInfoMapper incomeDataCleanInfoMapper;

    @Override
    public List<IncomeDataCleanVo> getTreeData(IncomeDataCleanVo vo) {
        String listNorm = vo.getInventoryNorm();
        List<ConfigInventoryChapter> configInventoryChapters = configInventoryChapterMapper.selectList(
                Wrappers.<ConfigInventoryChapter>lambdaQuery()
                        .eq(ConfigInventoryChapter::getCompanyId, vo.getCompanyId())
                        .eq(ConfigInventoryChapter::getType, "G")
                        .eq(ConfigInventoryChapter::getListNorm, listNorm)
        );
        return IncomeDataCleanVo.convert(configInventoryChapters);
    }

    @Override
    public TableDataInfo getGroupTableData(IncomeDataCleanVo vo) {
        List<IncomeDataCleanVo> res;
        Integer total;
        String type = vo.getType();
        Long companyId = vo.getCompanyId();
        String inventoryNorm = vo.getInventoryNorm();
        String categoryId = vo.getCategoryId();
        Map<String, String> codesMap = new HashMap<>();
        if(IncomeDataConstanta.Tabs.FB_0.getCode().equals(type)){
            //分部分项清单
            List<String> chapterIds = configInventoryChapterMapper.selectList(Wrappers.<ConfigInventoryChapter>lambdaQuery()
                    .eq(ConfigInventoryChapter::getCompanyId, companyId)
                    .apply("(id = '" + categoryId + "' or pid = '" + categoryId + "')")
            ).stream().map(ConfigInventoryChapter::getId).collect(Collectors.toList());
            List<ConfigInventoryLib> configInventoryLibs = configInventoryLibMapper.selectConfigInventoryLibList(new ConfigInventoryLib(){{
                setCompanyId(companyId);
                setListNorm(inventoryNorm);
                setType("G");
            }}, chapterIds);
            for (ConfigInventoryLib lib : configInventoryLibs) {
                codesMap.put(lib.getListCoding(), "1" + "@null" + "1");
            }
            total= incomeDataCleanMapper.countGroupTableDataOfFBQD(vo, codesMap.keySet(), getAllPriceType(vo.getPriceType()));
            PageUtils.startPage();
            res=incomeDataCleanMapper.getGroupTableDataOfFBQD(vo, codesMap.keySet(), getAllPriceType(vo.getPriceType()));
        }else{
            total = incomeDataCleanMapper.countGroupTableDataOfCSQD(vo, getAllPriceType(vo.getPriceType()));
            PageUtils.startPage();
            res = incomeDataCleanMapper.getGroupTableDataOfCSQD(vo, getAllPriceType(vo.getPriceType()));
        }
        if(IncomeDataConstanta.Tabs.FB_0.getCode().equals(type)){
            Map<String, String> finalCodesMap = codesMap;
            res = res.stream().peek(v -> {
                String val = finalCodesMap.get(v.getInventoryCode());
                if(StrUtil.isNotEmpty(val)){
                    String[] split = val.split("@null");
                    v.setInventoryContent(split[0]);
                    v.setInventoryCalcrule(split[1]);
                }
            }).collect(Collectors.toList());
        }
        return new TableDataInfo(res, total);
    }

    @Override
    public List<IncomeDataCleanVo> getDetailTableData(IncomeDataCleanVo vo) {
        String type = vo.getType();
        if (IncomeDataConstanta.Tabs.FB_0.getCode().equals(type)) {
            return incomeDataCleanMapper.selectDetailTableDataOfFBQD(vo, getAllPriceType(vo.getPriceType())).stream()
                    .peek(v -> v.setPriceType(CCBConstants.CCB_TYPE.getDescByCode(v.getPriceType())))
                    .peek(v -> {
                        if(StrUtil.isNotBlank(v.getDataJson())){
                            EcoBqitem bqitem = JSONUtil.toBean(v.getDataJson(), EcoBqitem.class);
                            v.setOinventoryCode(bqitem.getCode());
                            v.setOinventoryName(bqitem.getDescription());
                        }
                    })
                    .collect(Collectors.toList());
        }else{
            return incomeDataCleanMapper.selectDetailTableDataOfCSQD(vo, getAllPriceType(vo.getPriceType())).stream()
                    .peek(v -> v.setPriceType(CCBConstants.CCB_TYPE.getDescByCode(v.getPriceType())))
                    .peek(v -> {
                        if(StrUtil.isNotBlank(v.getDataJson())){
                            EcoMeasureitem measureitem = JSONUtil.toBean(v.getDataJson(), EcoMeasureitem.class);
                            v.setOinventoryCode(measureitem.getCode());
                            v.setOinventoryName(measureitem.getDescription());
                        }
                    })
                    .collect(Collectors.toList());
        }
    }

    @Override
    public Boolean enterClean(IncomeDataCleanVo vo) {
        Map<String, List<String>> selKey_ids = vo.getSelKeyLinkids();
        List<String> selKeys = vo.getSelKeys();
        String newKey = vo.getNewKey();
        String type = vo.getType();
        String cleanStatus = vo.getCleanStatus();
        if (StrUtil.isNotEmpty(newKey)) {
            List<String> cleanIds = new ArrayList<>();
            for (String selKey : selKeys) {
                Map<String, String> formatKey = this.formatKey(selKey);
                List<String> ids = selKey_ids.get(selKey);
                if (StrUtil.isNotEmpty(formatKey.get("groupId"))) {
                    String groupId = formatKey.get("groupId");
                    incomeDataCleanInfoMapper.delete(Wrappers.<IncomeDataCleanInfo>lambdaQuery()
                            .eq(IncomeDataCleanInfo::getPid, groupId)
                            .in(IncomeDataCleanInfo::getOid, ids)
                    );
                    int size = incomeDataCleanInfoMapper.selectList(Wrappers.<IncomeDataCleanInfo>lambdaQuery().eq(IncomeDataCleanInfo::getPid, groupId)).size();
                    if (size == 0) {
                        incomeDataCleanMapper.deleteById(groupId);
                    } else {
                        IncomeDataClean incomeDataClean = incomeDataCleanMapper.selectById(groupId);
                        incomeDataClean.setYycs(size);
                        incomeDataCleanMapper.updateById(incomeDataClean);
                    }
                }
                cleanIds.addAll(ids);
            }
            Map<String, String> formatKey = this.formatKey(newKey);
            IncomeDataClean cleanData = new IncomeDataClean();
            cleanData.setCleanStatus(cleanStatus);
            cleanData.setCleanDate(StrUtil.equals("清洗数据", cleanData.getCleanStatus()) ? new Date() : null);
            cleanData.setClassification(type);
            cleanData.setInventoryCode(formatKey.get("inventoryCode"));
            cleanData.setInventoryName(formatKey.get("inventoryName"));
            cleanData.setInventoryUnit(formatKey.get("inventoryUnit"));
            cleanData.setInventorySpec(formatKey.get("inventorySpec"));
            cleanData.setYycs(cleanIds.size());
            cleanData = this.saveCostDataClean(cleanData);
            if(IncomeDataConstanta.Tabs.FB_0.getCode().equals(type)){
                for (EcoBqitem item : ecoBqitemMapper.selectList(Wrappers.<EcoBqitem>lambdaQuery().in(EcoBqitem::getId, cleanIds))) {
                    IncomeDataCleanInfo info = new IncomeDataCleanInfo();
                    info.setDataJson(JSONUtil.toJsonStr(item));
                    info.setPid(cleanData.getId());
                    info.setOid(item.getId());

                    info.setOrginCode(cleanData.getInventoryCode());
                    info.setInventoryCode(cleanData.getInventoryCode());
                    info.setInventoryName(cleanData.getInventoryName());
                    info.setInventoryUnit(cleanData.getInventoryUnit());
                    info.setInventorySpec(cleanData.getInventorySpec());

                    info.setPrice(item.getRate());
                    info.setPriceType(item.getStagetype());
                    info.setProid(item.getProId());
                    info.setLinkDataJson(JSONUtil.toJsonStr(Collections.emptyList()));

                    List<Integer> feeitemids = ecoBqitemmateMapper.selectList(Wrappers.<EcoBqitemmate>lambdaQuery()
                            .eq(EcoBqitemmate::getProId, item.getProId())
                            .eq(EcoBqitemmate::getStagetype, item.getStagetype())
                            .eq(EcoBqitemmate::getSrctableid, item.getBqitemid())
                    ).stream().map(EcoBqitemmate::getRelationid).collect(Collectors.toList());

                    if(feeitemids.size()>0){
                        List<EcoCbfeeitem> ecoCbfeeitems = cbfeeitemMapper.selectList(Wrappers.<EcoCbfeeitem>lambdaQuery()
                                .eq(EcoCbfeeitem::getProId, item.getProId())
                                .eq(EcoCbfeeitem::getStagetype, item.getStagetype())
                                .in(EcoCbfeeitem::getCbfeeitemid, feeitemids)
                        );
                        info.setLinkDataJson(JSONUtil.toJsonStr(ecoCbfeeitems));
                    }

                    info.setInventoryContent("1");
                    info.setInventoryCalcrule("1");

                    incomeDataCleanInfoMapper.insert(info);
                }
            }else{
                for (EcoMeasureitem item : ecoMeasureitemMapper.selectList(Wrappers.<EcoMeasureitem>lambdaQuery().in(EcoMeasureitem::getId, cleanIds))) {
                    IncomeDataCleanInfo info = new IncomeDataCleanInfo();
                    info.setDataJson(JSONUtil.toJsonStr(item));
                    info.setPid(cleanData.getId());
                    info.setOid(item.getId());

                    info.setOrginCode(cleanData.getInventoryCode());
                    info.setInventoryCode(cleanData.getInventoryCode());
                    info.setInventoryName(cleanData.getInventoryName());
                    info.setInventoryUnit(cleanData.getInventoryUnit());
                    info.setInventorySpec(cleanData.getInventorySpec());

                    info.setPrice(item.getRate());
                    info.setPriceType(item.getStagetype());
                    info.setProid(item.getProId());

                    info.setInventoryContent("1");
                    info.setInventoryCalcrule("1");

                    incomeDataCleanInfoMapper.insert(info);
                }
            }
        } else {
            for (String selKey : selKeys) {
                Map<String, String> formatKey = this.formatKey(selKey);
                List<String> ids = selKey_ids.get(selKey);
                IncomeDataClean cleanData = new IncomeDataClean();
                if (StrUtil.isNotEmpty(formatKey.get("groupId"))) {
                    String groupId = formatKey.get("groupId");
                    incomeDataCleanInfoMapper.delete(Wrappers.<IncomeDataCleanInfo>lambdaQuery()
                            .eq(IncomeDataCleanInfo::getPid, groupId)
                            .in(IncomeDataCleanInfo::getOid, ids)
                    );
                    int size = incomeDataCleanInfoMapper.selectList(Wrappers.<IncomeDataCleanInfo>lambdaQuery().eq(IncomeDataCleanInfo::getPid, groupId)).size();
                    if (size == 0) {
                        incomeDataCleanMapper.deleteById(groupId);
                    } else {
                        IncomeDataClean incomeDataClean = incomeDataCleanMapper.selectById(groupId);
                        incomeDataClean.setYycs(size);
                        incomeDataCleanMapper.updateById(incomeDataClean);
                    }
                }
                cleanData.setCleanStatus(cleanStatus);
                cleanData.setCleanDate(StrUtil.equals("清洗数据", cleanData.getCleanStatus()) ? new Date() : null);
                cleanData.setClassification(type);
                cleanData.setInventoryCode(formatKey.get("inventoryCode"));
                cleanData.setInventoryName(formatKey.get("inventoryName"));
                cleanData.setInventoryUnit(formatKey.get("inventoryUnit"));
                cleanData.setInventorySpec(formatKey.get("inventorySpec"));
                cleanData.setYycs(ids.size());
                cleanData = this.saveCostDataClean(cleanData);
                if (IncomeDataConstanta.Tabs.FB_0.getCode().equals(type)) {
                    for (EcoBqitem item : ecoBqitemMapper.selectList(Wrappers.<EcoBqitem>lambdaQuery().in(EcoBqitem::getId, ids))) {
                        IncomeDataCleanInfo info = new IncomeDataCleanInfo();
                        info.setDataJson(JSONUtil.toJsonStr(item));
                        info.setPid(cleanData.getId());
                        info.setOid(item.getId());

                        info.setOrginCode(cleanData.getInventoryCode());
                        info.setInventoryCode(cleanData.getInventoryCode());
                        info.setInventoryName(cleanData.getInventoryName());
                        info.setInventoryUnit(cleanData.getInventoryUnit());
                        info.setInventorySpec(cleanData.getInventorySpec());

                        info.setPrice(item.getRate());
                        info.setPriceType(item.getStagetype());
                        info.setProid(item.getProId());

                        List<Integer> feeitemids = ecoBqitemmateMapper.selectList(Wrappers.<EcoBqitemmate>lambdaQuery()
                                .eq(EcoBqitemmate::getProId, item.getProId())
                                .eq(EcoBqitemmate::getStagetype, item.getStagetype())
                                .eq(EcoBqitemmate::getSrctableid, item.getBqitemid())
                        ).stream().map(EcoBqitemmate::getRelationid).collect(Collectors.toList());

                        if(feeitemids.size()>0){
                            List<EcoCbfeeitem> ecoCbfeeitems = cbfeeitemMapper.selectList(Wrappers.<EcoCbfeeitem>lambdaQuery()
                                    .eq(EcoCbfeeitem::getProId, item.getProId())
                                    .eq(EcoCbfeeitem::getStagetype, item.getStagetype())
                                    .in(EcoCbfeeitem::getCbfeeitemid, feeitemids)
                            );
                            info.setLinkDataJson(JSONUtil.toJsonStr(ecoCbfeeitems));
                        }

                        info.setInventoryContent("1");
                        info.setInventoryCalcrule("1");

                        incomeDataCleanInfoMapper.insert(info);
                    }
                } else {
                    for (EcoMeasureitem item : ecoMeasureitemMapper.selectList(Wrappers.<EcoMeasureitem>lambdaQuery().in(EcoMeasureitem::getId, ids))) {
                        IncomeDataCleanInfo info = new IncomeDataCleanInfo();
                        info.setDataJson(JSONUtil.toJsonStr(item));
                        info.setPid(cleanData.getId());
                        info.setOid(item.getId());

                        info.setOrginCode(cleanData.getInventoryCode());
                        info.setInventoryCode(cleanData.getInventoryCode());
                        info.setInventoryName(cleanData.getInventoryName());
                        info.setInventoryUnit(cleanData.getInventoryUnit());
                        info.setInventorySpec(cleanData.getInventorySpec());

                        info.setPrice(item.getRate());
                        info.setPriceType(item.getStagetype());
                        info.setProid(item.getProId());


                        info.setInventoryContent("1");
                        info.setInventoryCalcrule("1");

                        incomeDataCleanInfoMapper.insert(info);
                    }
                }
            }
        }
        return true;
    }

    @Override
    public Boolean allEnterClean(IncomeDataCleanVo vo) {

        List<IncomeDataCleanVo> res;
        String type = vo.getType();
        Long companyId = vo.getCompanyId();
        String inventoryNorm = vo.getInventoryNorm();
        String categoryId = vo.getCategoryId();
        Map<String, String> codesMap = new HashMap<>();
        if (IncomeDataConstanta.Tabs.FB_0.getCode().equals(type)) {
            //分部分项清单
            List<String> chapterIds = configInventoryChapterMapper.selectList(Wrappers.<ConfigInventoryChapter>lambdaQuery()
                    .eq(ConfigInventoryChapter::getCompanyId, companyId)
                    .apply("(id = '" + categoryId + "' or pid = '" + categoryId + "')")
            ).stream().map(ConfigInventoryChapter::getId).collect(Collectors.toList());
            List<ConfigInventoryLib> configInventoryLibs = configInventoryLibMapper.selectConfigInventoryLibList(new ConfigInventoryLib() {{
                setCompanyId(companyId);
                setListNorm(inventoryNorm);
                setType("G");
            }}, chapterIds);
            for (ConfigInventoryLib lib : configInventoryLibs) {
                codesMap.put(lib.getListCoding(), "1" + "@null" + "1");
            }
            res = incomeDataCleanMapper.getGroupTableDataOfFBQD(vo, codesMap.keySet(), getAllPriceType(vo.getPriceType()));
        } else {
            res = incomeDataCleanMapper.getGroupTableDataOfCSQD(vo, getAllPriceType(vo.getPriceType()));
        }

        vo.setNewKey(null);
        vo.setCleanStatus("清洗数据");
        Map<String, List<String>> selKey_ids = new HashMap<>();
        List<String> selKeys = new ArrayList<>();
        for (IncomeDataCleanVo incomeDataCleanVo : res) {
            vo.setInventoryCode(incomeDataCleanVo.getInventoryCode());
            vo.setInventorySpec(incomeDataCleanVo.getInventorySpec());
            vo.setInventoryName(incomeDataCleanVo.getInventoryName());
            vo.setInventoryUnit(incomeDataCleanVo.getInventoryUnit());
            vo.setGroupId(incomeDataCleanVo.getId());
            List<IncomeDataCleanVo> detailTableData = this.getDetailTableData(vo);
            String key = (StrUtil.isBlank(incomeDataCleanVo.getId()) ? "@null" : incomeDataCleanVo.getId()) + "$$" +
                    (StrUtil.isBlank(incomeDataCleanVo.getInventoryCode()) ? "@null" : incomeDataCleanVo.getInventoryCode()) + "$$" +
                    (StrUtil.isBlank(incomeDataCleanVo.getInventoryName()) ? "@null" : incomeDataCleanVo.getInventoryName()) + "$$" +
                    (StrUtil.isBlank(incomeDataCleanVo.getInventoryUnit()) ? "@null" : incomeDataCleanVo.getInventoryUnit()) + "$$" +
                    (StrUtil.isBlank(incomeDataCleanVo.getInventorySpec()) ? "@null" : incomeDataCleanVo.getInventorySpec());
            selKeys.add(key);
            selKey_ids.put(key, detailTableData.stream().map(IncomeDataCleanVo::getId).collect(Collectors.toList()));
        }
        vo.setSelKeyLinkids(selKey_ids);
        vo.setSelKeys(selKeys);
        this.enterClean(vo);
        return true;
    }

    @Override
    public TableDataInfo getInventoryData(IncomeDataCleanVo vo) {
        Long companyId = vo.getCompanyId();
        String inventoryNorm = vo.getInventoryNorm();
        String categoryId = vo.getCategoryId();
        //分部分项清单
        List<String> chapterIds = configInventoryChapterMapper.selectList(Wrappers.<ConfigInventoryChapter>lambdaQuery()
                .eq(ConfigInventoryChapter::getCompanyId, companyId)
                .apply("(id = '" + categoryId + "' or pid = '" + categoryId + "')")
        ).stream().map(ConfigInventoryChapter::getId).collect(Collectors.toList());
        Integer selectCount = configInventoryLibMapper.selectConfigInventoryLibList(new ConfigInventoryLib() {{
            setCompanyId(companyId);
            setListNorm(inventoryNorm);
            setType("G");
        }}, chapterIds).size();
        PageUtils.startPage();
        List<ConfigInventoryLib> configInventoryLibs = configInventoryLibMapper.selectConfigInventoryLibList(new ConfigInventoryLib() {{
            setCompanyId(companyId);
            setListNorm(inventoryNorm);
            setType("G");
        }}, chapterIds);
        List<IncomeDataCleanVo> collect = configInventoryLibs.stream().map(v -> {
            IncomeDataCleanVo re = new IncomeDataCleanVo();
            re.setId(v.getId());
            re.setInventoryCode(v.getListCoding());
            re.setInventoryName(v.getListName());
            re.setInventoryUnit(v.getUnit());
            re.setInventoryContent(v.getFeaturesContent());
            re.setInventoryCalcrule(v.getCalcuationRules());
            return re;
        }).collect(Collectors.toList());
        return new TableDataInfo(collect,selectCount);
    }

    private IncomeDataClean saveCostDataClean(IncomeDataClean one) {
        if (StrUtil.isNotEmpty(one.getId()))
            incomeDataCleanMapper.updateById(one);
        else
            incomeDataCleanMapper.insert(one);
        return one;
    }

    private Set<String> getAllPriceType(String oldPriceType) {
        Set<String> priceTypes = new HashSet<>();
        if (StrUtil.equals("全部", oldPriceType)) {
            IncomeDataCleanService.IncomeProjectTypeKV.forEach(v -> priceTypes.add(v.get("key")));
        } else {
            priceTypes.add(oldPriceType);
        }
        return priceTypes;
    }

    private Map<String, String> formatKey(String key) {
        String[] split = key.split("\\$\\$");
        String groupId = split[0];
        String inventoryCode = split[1];
        String inventoryName = split[2];
        String inventoryUnit = split[3];
        String inventorySpec = split[4];
        if (StrUtil.equals("@null", groupId)) groupId = null;
        if (StrUtil.equals("@null", inventoryCode)) inventoryCode = null;
        if (StrUtil.equals("@null", inventoryName)) inventoryName = null;
        if (StrUtil.equals("@null", inventoryUnit)) inventoryUnit = null;
        if (StrUtil.equals("@null", inventorySpec)) inventorySpec = null;

        String finalGroupId = groupId;
        String finalinventoryCode = inventoryCode;
        String finalinventoryName = inventoryName;
        String finalinventoryUnit = inventoryUnit;
        String finalinventorySpec = inventorySpec;
        return new HashMap<String, String>() {{
            put("groupId", finalGroupId);
            put("inventoryCode", finalinventoryCode);
            put("inventoryName", finalinventoryName);
            put("inventoryUnit", finalinventoryUnit);
            put("inventorySpec", finalinventorySpec);
        }};
    }
}
